#!/usr/bin/env bash

__rvm_log_command_caclulate_log_timestamp()
{
  export rvm_log_timestamp="$(__rvm_date "+%s")"
  rvm_debug "Log prefix: ${rvm_log_path}/${rvm_log_timestamp}${rvm_ruby_string:+_}${rvm_ruby_string:-}/"
}

__rvm_log_command_caclulate_log_filesystem()
{
  export rvm_log_filesystem="$(
    __rvm_mount 2>/dev/null | __rvm_awk -v rvm_path=$rvm_path '
      BEGIN{longest=""; fstype=""}
      {if (index(rvm_path,$3)==1 && length($3)>length(longest)){longest=$3; fstype=$5}}
      END{print fstype}
    '
  )"
  rvm_debug "Log filesystem: ${rvm_log_filesystem}"
}

__rvm_log_command_caclulate_log_namelen()
{
  case "${rvm_log_filesystem}" in
    (ecryptfs) export rvm_log_namelen=138 ;;
    (*)        export rvm_log_namelen=250 ;;
  esac
  rvm_debug "Log max name length: ${rvm_log_namelen}"
}

__rvm_log_command_caclulate_log_file_name()
{
  [[ -n "${rvm_log_timestamp:-}"  ]] || __rvm_log_command_caclulate_log_timestamp
  [[ -n "${rvm_log_filesystem:-}" ]] || __rvm_log_command_caclulate_log_filesystem
  [[ -n "${rvm_log_namelen:-}"    ]] || __rvm_log_command_caclulate_log_namelen
  name="${name//[ \/]/_}"
  _log="${rvm_log_path}/${rvm_log_timestamp}${rvm_ruby_string:+_}${rvm_ruby_string:-}/${name}"
  if [[ -n "${ZSH_VERSION:-}" ]]
  then _log="${_log[0,${rvm_log_namelen}]}.log"
  else _log="${_log:0:${rvm_log_namelen}}.log"
  fi
}

# Run a specified command and log it (once).
__rvm_log_command()
{
  \typeset name message _command_start _command_name
  \typeset -a _command

  name="${1:-}"
  message="${2:-}"
  shift 2
  _command=( "$@" )   # store full command so we can manipulate it
  _command_start="$1" # store first part so we can detect variables
  while (( $# )) && [[ "$1" == *"="* ]] # skip variables from beginning
  do shift
  done
  _command_name="$1"  # store the real command so we can detect functions

  [[ "${_command_start}" != *"="* ]] || _command=( "env" "${_command[@]}" )
  if __function_on_stack __rvm_log_command_internal
  then __rvm_log_command_simple   "$@" || return $?
  else __rvm_log_command_internal "$@" || return $?
  fi
}

# basic debugging information for the command
__rvm_log_command_debug()
{
  printf "%b" "[$(__rvm_date +'%Y-%m-%d %H:%M:%S')] ${_command_name}\n"
  if is_a_function "${_command_name}"
  then \typeset -f  "${_command_name}"
  fi
  printf "%b" "current path: $PWD\n"
  env | __rvm_grep -E '^GEM_HOME=|^GEM_PATH=|^PATH='
  printf "%b" "command(${#_command[@]}): ${_command[*]}\n"
}

# Run a specified command and do not log it again.
__rvm_log_command_simple()
{
  __rvm_log_command_debug
  rvm_log "$message"
  "$@" || return $?
}

# Run a specified command and log it.
__rvm_log_command_internal()
{
  \typeset _log

  (( ${rvm_niceness:-0} == 0 ))      || _command=( nice -n $rvm_niceness "${_command[@]}" )

  __rvm_log_command_caclulate_log_file_name
  rvm_debug "Log file: ${_log}"

  [[ -d "${_log%\/*}" ]] || \command \mkdir -p "${_log%\/*}"
  [[ -f "${_log}"     ]] || \command \rm -f "${_log}"

  __rvm_log_command_debug | tee "${_log}" | rvm_debug_stream

  __rvm_log_dotted "${_log}" "$message" "${_command[@]}" ||
  {
    \typeset result=$?
    \typeset __show_lines="${rvm_show_log_lines_on_error:-0}"
    rvm_error "Error running '${_command[*]}',"
    case "${__show_lines}" in
      (0)
        rvm_error "please read ${_log}"
        ;;
      (all)
        rvm_error "content of log ${_log}"
        cat "${_log}" >&6
        ;;
      (*)
        rvm_error "showing last ${__show_lines} lines of ${_log}"
        tail -n "${__show_lines}" "${_log}" >&6
        ;;
    esac
    return ${result}
  }
}

__rvm_debug_command()
{
  rvm_debug "Running($#): $*"
  "$@" || return $?
}

__rvm_pager_or_cat_v()
{
  eval "${PAGER:-\command \cat} '$1'"
}

__rvm_ask_for()
{
  \typeset response
  rvm_warn "$1"
  printf "%b" "(anything other than '$2' will cancel) > "

  # need and IF to properly handle CTRL+C ... wtf?
  if read response && [[ "$2" == "$response" ]]
  then return 0
  else return 1
  fi
}

__rvm_dotted()
{
  set +x
  \typeset flush

  if (( $# ))
  then printf "%b" "${rvm_notify_clr:-}$*${rvm_reset_clr:-}"
  fi

  if __rvm_awk '{fflush;}' <<<EO 2>/dev/null
  then flush=fflush
  else flush=flush
  fi

  # the nasty '${flush}' inside is for compatibility,
  # old awk does not allow running function from variable
  awk -v go_back="$( tput cub1 2>/dev/null || true)" \
'
  BEGIN{
    spin[0]="|"go_back;
    spin[1]="/"go_back;
    spin[2]="-"go_back;
    spin[3]="\\"go_back }
  {
    if ((NR-1)%(10)==9)
      printf ".";
    else
      if (go_back!="") printf spin[(NR-1)%4];
    '${flush}' }
  END{
    print "." }
  '
}

__rvm_log_dotted()
{
  \typeset __log_file __message __iterator __result __local_rvm_trace_flag
  __log_file="$1"
  __message="$2"
  shift 2
  __result=0
  __local_rvm_trace_flag=${rvm_trace_flag:-0}
  if
    (( ${rvm_trace_flag:-0} ))
  then
    {
      set -x
      "$@" 2>&1 | tee -a "${__log_file}"
      __rvm_check_pipestatus ${PIPESTATUS[@]} ${pipestatus[@]} || __result=$?
      (( __local_rvm_trace_flag > 0 )) || set +x
    } 1>&2
  elif
    [[ -n "${ZSH_VERSION:-}" ]]
  then
    rvm_log "${__message} - please wait"
    {
      set -x
      "$@" > "${__log_file}" 2>&1 || __result=$?
      (( __local_rvm_trace_flag > 0 )) || set +x
    } 2>/dev/null
  else
    {
      set -x
      "$@" 2>&1 | tee -a "${__log_file}" | __rvm_dotted "${__message}"
      __rvm_check_pipestatus ${PIPESTATUS[@]} ${pipestatus[@]} || __result=$?
      (( __local_rvm_trace_flag > 0 )) || set +x
    } 2>/dev/null
  fi
  return $__result
}

__rvm_check_pipestatus()
{
  for __iterator
  do
    case "${__iterator}" in
      ("") true ;;
      (0)  true ;;
      (*)  return ${__iterator} ;;
    esac
  done
  return 0
}

__rvm_wait_anykey()
{
  if [[ -n "${1:-}" ]]
  then echo "$1"
  fi
  \typeset _read_char_flag
  if [[ -n "${ZSH_VERSION:-}" ]]
  then _read_char_flag=k
  else _read_char_flag=n
  fi
  builtin read -${_read_char_flag} 1 -s -r anykey
}

__rvm_table_br()
{
  \typeset width=${COLUMNS:-78}
  width=$(( width > 116 ? 116 : width ))
  printf "%-${width}s\n" " " | __rvm_sed 's/ /*/g'
}

__rvm_fold()
{
  if fold -s -w 10 <<<bla >/dev/null
  then fold -s -w $1
  else fold    -w $1
  fi
}

__rvm_table_wrap_text()
{
  \typeset width=${COLUMNS:-78}
  width=$(( width > 116 ? 116 : width ))
  width=$(( width - 4 )) # "* <content> *"
  __rvm_fold $width | __rvm_awk -v width=$width '{printf "* %-"width"s *\n", $0}'
}

# echo text | __rvm_table [header]
__rvm_table()
{
  if
    [[ -n "${1:-}" ]]
  then
    __rvm_table_br
    echo "$1" | __rvm_table_wrap_text
  fi
  __rvm_table_br
  \command \cat "${2:--}" | __rvm_table_wrap_text
  __rvm_table_br
}
